<template>
  <PageWrapper v-loading="loading" loading-tip="加载中...">
    <div class="p-4 p-4-tag">
      <div class="tag" ref="divDom">
        <div class="main-nav">
          <div class="search-box" style="width:101%">
            <a-input-search
              v-model:value="searchDriver"
              placeholder="搜索"
              :allowClear="true"
              @search="onSearchDriver"
            />
          </div>
          <BasicTree
            title=""
            ref="treeRef"
            :treeData="treeDataPro"
            :beforeRightClick="getRightMenuList"
            :fieldNames="{ key: 'Key', title: 'Name', children: 'Children' }"
            :onSelect="handleTreeSelect"
          />
        </div>
        <div class="main-content">
          <BasicTable
            @register="registerTable"
            :columns="columns"
            :loading="tableLoading"
            :dataSource="tableData"
            :canResize="false"
            :showIndexColumn="false"
            rowKey="FullName"
            :striped="true"
            :bordered="true"
            :pagination="false"
          >
            <template #bodyCell="{ column, record }">
              <template v-if="column.key === 'Value'">
                <div class="value-style" @dblclick="handleDbClick(record)">{{ record.Value }}</div>
              </template>
            </template>
            <template #toolbar>
              <div class="cutsom-title" v-if="deviceInfo.name">
                <div class="cutsom-title-item">
                  设备状态<span
                    :style="`background-color:${deviceInfo.isOnline ? 'green' : '#ccccce'}`"
                  ></span>
                </div>
                <div class="cutsom-title-item cutsom-title-item-flex">
                  <div class="label">IOT设备编码：</div
                  ><div class="val">{{ deviceInfo.fullName }}</div>
                </div>
                <div class="cutsom-title-item cutsom-title-item-flex">
                  <div class="label">设备编码：</div><div class="val">{{ deviceInfo.code }}</div>
                </div>
                <div class="cutsom-title-item cutsom-title-item-flex">
                  <div class="label">设备名称：</div><div class="val">{{ deviceInfo.name }}</div>
                </div>
                <div class="cutsom-title-item cutsom-title-item-flex">
                  <div class="label">设备型号：</div
                  ><div class="val">{{ deviceInfo.model_code }}</div>
                </div>
                <div class="cutsom-title-item cutsom-title-item-flex">
                  <div class="label">设备类型：</div
                  ><div class="val">{{ deviceInfo.type_name }}</div>
                </div>
              </div>
              <a-input-search
                v-model:value="searchValue"
                placeholder="请输入搜索的变量"
                style="width: 200px"
                :allowClear="true"
                @search="onSearch"
                v-if="isShowSearch"
              />
              <a-button type="primary" class="btn-box-item"> 导出 </a-button>
            </template>
          </BasicTable>
          <div class="flex py-2 items-center justify-end pagination-box">
            <a-pagination
              :show-total="(total) => `共 ${total} 条数据`"
              showSizeChanger
              size="small"
              :current="paginationInfo.data.current"
              :pageSize="paginationInfo.data.pageSize"
              :total="paginationInfo.data.total"
              @change="handlePageChange"
            />
          </div>
        </div>
      </div>
    </div>
    <modelByDetail
      @register="registerByDetail"
      @submit-success="handleUpdateTable"
      :info="detailForm"
    />
    <!-- 设备的表单弹窗 -->
    <modelByDrive :formType="formType" @register="registerByDrive" />
    <!-- 分组的表单弹窗 -->
    <modelByGroup :formType="formType" @register="registerByGroup" />
  </PageWrapper>
</template>

<script lang="ts" setup>
  import { PageWrapper } from '/@/components/Page';
  import { BasicTable, useTable } from '/@/components/Table';
  import { Pagination } from 'ant-design-vue';

  import modelByDetail from '/@/views/project/eqIntegration/components/modelByDetail.vue';
  import { usePermission } from '/@/hooks/web/usePermission';
  import modelByDrive from '/@/views/project/tag/components/modelByDrive.vue';
  import modelByGroup from '/@/views/project/tag/components/modelByGroup.vue';
  import { useModal } from '/@/components/Modal';
  import { BasicColumn } from '/@/components/Table/src/types/table';
  import { useWebSocket } from '@vueuse/core';
  import {
    reactive,
    ref,
    unref,
    onMounted,
    nextTick,
    watchEffect,
    onBeforeUnmount,
    computed,
  } from 'vue';
  import { BasicTree, TreeActionType, ContextMenuItem } from '/@/components/Tree/index';
  import { useMessage } from '/@/hooks/web/useMessage';
  import {
    getRunTimeDriverTree,
    getRunTimeTagInfo,
    getDataType,
    getDeviceState,
    getGroupInfo,
    getDriverInfo,
  } from '/@/api/tag/index';
  import { getdeviceenterprise } from '/@/api/equipmentLedger/index';

  const APagination = Pagination;

  let tableParams: any = reactive({
    driveId: '',
    groupId: '',
  });
  let detailForm: any = reactive({ data: {} });
  let formType = reactive<any>({
    type: 0, //0是设备，1是分组
    operationType: 0, //0是新增，1是编辑,2是编辑
    id: '', //要编辑的id
    driveId: '', //设备id针对分组的
    nodeName: '', //节点专用
    getDriverInfo,
    getGroupInfo,
  });
  let deviceInfo = ref({
    name: '',
    fullName: '',
    code: '',
    model_code: '',
    type_name: '',
    isOnline: false,
  });
  const { hasPermission } = usePermission();
  let typeOptions: any = reactive([]);
  let searchValue = ref('');
  let curType = ref(0);
  let isSearch = false;
  let treeDataPro: any = ref([]);
  let loading = ref(false);
  let tableLoading = ref(false);
  let searchDriver = ref('');
  let tableData: any = reactive([]);
  // 分页信息
  let paginationInfo = reactive({
    data: {
      pageSize: 50,
      total: 0,
      current: 1,
    },
  });
  // 表单数据
  let columns: BasicColumn[] = [
    {
      title: '变量',
      dataIndex: 'Name',
      width: 150,
    },
    {
      title: '地址',
      dataIndex: 'Address',
    },
    {
      title: '数据类型',
      dataIndex: 'DataTypeCn',
    },
    {
      title: '值',
      dataIndex: 'Value',
    },

    {
      title: '质量戳',
      dataIndex: 'QualityStamp',
      width: 100,
    },
    {
      title: '原始值',
      dataIndex: 'WriteValue',
    },

    {
      title: '写入质量戳',
      dataIndex: 'WriteQuality',
      width: 100,
    },
    {
      title: '时间戳',
      dataIndex: 'Timestamp',
    },
    {
      title: '单位',
      dataIndex: 'Unit',
      width: 100,
    },
    {
      title: '描述',
      dataIndex: 'Description',
    },
  ];
  const { createMessage } = useMessage();

  const [registerTable, { updateTableDataRecord }] = useTable();
  const [registerByDetail, { openModal: openModalByDetail, closeModal: closeModalByDetail }] =
    useModal();
  const [registerByDrive, { openModal: openModalByDrive }] = useModal();
  const [registerByGroup, { openModal: openModalByGroup }] = useModal();

  const treeRef = ref<Nullable<TreeActionType>>(null);
  const divDom: any = ref(null);
  const isShowSearch = computed(() => curType.value === 2 || curType.value === 1);

  onMounted(async () => {
    initData();
    typeOptions = await getDataType();
  });
  onBeforeUnmount(() => {
    close();
  });
  const state = reactive({
    server: 'ws://192.168.0.11:8056',
  });
  if (process.env.NODE_ENV === 'production') {
    const loaclhostNames = window.location.href.split('/');
    // 如果配置访问url则取配置文件的
    const webSocketUrl = sessionStorage.getItem('webSocketUrl');
    if (webSocketUrl) {
      state.server = `${webSocketUrl}`;
    } else if (loaclhostNames?.length > 0 && loaclhostNames[2]) {
      const domain = loaclhostNames[2].split(':')[0];
      state.server = `ws://${domain}:8056`;
    }
  }
  const { data, close } = useWebSocket(state.server, {
    // immediate: false,
    autoReconnect: {
      retries: 20,
      delay: 10000,
      onFailed() {
        createMessage.error('重新连接失败');
      },
    },
    heartbeat: {
      interval: 10000,
    },
  });
  watchEffect(() => {
    if (data.value) {
      const res = JSON.parse(data.value);

      updateTableData(res);
    }
  });
  // 右键菜单
  function getRightMenuList(node: any): ContextMenuItem[] {
    let targetName = node.Type === 1 ? '设备' : '分组';
    return [
      {
        hidden: !(
          ([1].indexOf(node.Type) >= 0 && hasPermission('6-3-lookDevice')) ||
          (!node.CreatedByTemplate && node.Type === 2 && hasPermission('6-3-lookGroup'))
        ),
        label: `查看${targetName}`,
        handler: () => {
          handleSetFormType(node, 2);
          if (node.Type === 1) {
            openModalByDrive(true, {});
          } else if (node.Type === 2) {
            openModalByGroup(true, {});
          }
        },
        icon: 'ant-design:eye-outlined',
      },
    ];
  }

  function handleSetFormType(v, operationType) {
    let { Type, ConfigKey, ConfigParentkey, title } = v;
    formType.operationType = operationType;
    formType.nodeName = Type === 3 ? title : null;
    formType.type =
      [0, 3].indexOf(Type) >= 0 || ([1].indexOf(Type) >= 0 && [1, 2].indexOf(operationType) >= 0)
        ? 0
        : 1;
    formType.id = [1, 2].indexOf(operationType) >= 0 ? ConfigKey : '';
    formType.driveId = [1, 2].indexOf(operationType) >= 0 ? ConfigParentkey : ConfigKey;
  }
  // 搜索设备
  function onSearchDriver() {
    initData();
  }
  // 搜索方法
  function onSearch() {
    isSearch = ['', null, undefined].indexOf(searchValue.value) === -1;
    paginationInfo.data.current = 1;
    setTagList();
  }

  function handleDbClick(record) {
    detailForm.data = record;
    openModalByDetail();
  }
  function handlePageChange(page, pageSize) {
    paginationInfo.data.current = page;
    paginationInfo.data.pageSize = pageSize;
    setTagList();
  }
  function handleUpdateTable() {
    closeModalByDetail();
    setTimeout(() => {
      // paginationInfo.data.current = 1;
      setTagList();
    }, 250);
  }
  function updateTableData(val) {
    if (val) updateTableDataRecord(val.FullName, val);
  }
  function getTree() {
    const tree = unref(treeRef);
    if (!tree) {
      throw new Error('tree is null!');
    }
    return tree;
  }
  function eachTree(treeDatas: any[]) {
    treeDatas.forEach((element) => {
      element.title = element.Name;
      element.isShowOnline = element.Type === 1;
      switch (element.Type) {
        case 0:
          element.icon = 'ant-design:home-outlined';
          break;
        case 1:
          element.icon = 'ant-design:database-outlined';
          break;
        case 2:
          element.icon = 'ant-design:bars-outlined';
          break;
        case 3:
          element.icon = 'ant-design:folder-outlined';
          break;
        case 4:
          element.icon = 'ant-design:folder-outlined';
        default:
          break;
      }
      if (element.Children) eachTree(element.Children);
    });
  }
  async function initData() {
    loading.value = true;
    let resByTree = await getRunTimeDriverTree(searchDriver.value ? [searchDriver.value] : [null]);
    eachTree(resByTree);
    treeDataPro.value = resByTree || [];
    nextTick(() => {
      getTree().filterByLevel(1);
    });
    loading.value = false;
  }

  async function getStatus(name) {
    let isOnline = false;
    try {
      isOnline = await getDeviceState([name]);
    } catch (_err) {}
    return isOnline;
  }
  async function handleTreeSelect(_e, info) {
    searchValue.value = '';
    deviceInfo.value = {
      name: '',
      fullName: '',
      code: '',
      model_code: '',
      type_name: '',
      isOnline: false,
    };
    let { Type, Children = [], Parentkey, key } = info.node;
    curType.value = +Type;
    if ((Type === 1 && Children && Children.length > 0) || Type === 2) {
      let targetGroup = Type === 1 ? Children[0] : info.node;
      deviceInfo.value.isOnline = await getStatus(Type === 1 ? key : Parentkey);
      let resByInfo = await getdeviceenterprise([Type === 1 ? key : Parentkey]);
      deviceInfo.value = { ...deviceInfo.value, ...resByInfo };
      tableParams.groupId = targetGroup.Key;
      tableParams.driveId = targetGroup.Parentkey;
      paginationInfo.data.current = 1;

      setTagList();
    } else {
      tableData = [];
      tableParams.groupId = '-1';
      tableParams.driveId = '-1';
    }
  }
  async function setTagList() {
    try {
      tableLoading.value = true;
      let res = await getRunTimeTagInfo([
        {
          DriverKey: tableParams.driveId,
          GroupKey: tableParams.groupId,
          PageNO: paginationInfo.data.current,
          SearchValue: isSearch ? searchValue.value : '',
          PageSize: paginationInfo.data.pageSize,
        },
      ]);
      paginationInfo.data.total = res.TotalRows;

      tableData = res.Rows.map((item) => {
        item.ArchiveCn = item.Archive ? '是' : '否';
        let targetTypes = typeOptions.filter((v) => v.Value === item.DataType);
        item.DataTypeCn = targetTypes.length > 0 ? targetTypes[0].Key : '';
        item.WriteValue =
          ['', null, undefined].indexOf(item.WriteValue) >= 0
            ? item.WriteValue
            : item.WriteValue.toString();
        return item;
      });
      tableLoading.value = false;
    } catch (error) {
      tableLoading.value = false;
    }
  }
</script>

<style scoped lang="less">
  .p-4-tag {
    width: 100%;
    height: 100%;
    padding: 0px !important;
  }

  .tag {
    position: relative;
    overflow: hidden;
    height: 100%;
    // background-color: #fff;

    .main-nav {
      position: absolute;
      top: 0;
      left: 0;
      bottom: 0;
      width: 240px;
      height: 100%;
      padding: 8px;
      box-sizing: border-box;
      // overflow: auto;
      background-color: rgba(8, 30, 66, 0.04);
      border-radius: 3px;
    }

    .main-content {
      position: relative;
      height: 100%;
      margin-left: 243px;
      overflow: hidden;

      .pagination-box {
        z-index: 9;
        padding: 10px 5px;
        box-sizing: border-box;
        position: absolute;
        width: 100%;
        bottom: 0;
        left: 0;
        right: 0;
        // background-color: #fff;
      }
    }

    .main-content::after {
      content: '';
      display: block;
      width: 100%;
      height: 45px;
    }
  }

  .value-style {
    cursor: pointer;
    width: 100%;
    text-align: center;
    min-height: 17px;
  }

  .cutsom-title {
    flex: 1;
    display: flex;
    flex-wrap: wrap;

    .cutsom-title-item {
      margin-right: 20px;
      min-width: 80px;
      font-size: 12px;

      > span {
        display: inline-flex;
        background-color: green;
        width: 10px;
        height: 10px;
        border-radius: 50%;
        margin-left: 5px;
      }
    }

    .cutsom-title-item-flex {
      display: flex;

      .label {
        color: rgb(198, 198, 198);
      }
    }
  }
</style>
